﻿using System;
using System.Linq;
using System.Windows.Forms;
using Map;
using Map_Creator.Painters;
using Microsoft.Xna.Framework.Graphics;
using XnaPoint = Microsoft.Xna.Framework.Point;
using XnaRectangle = Microsoft.Xna.Framework.Rectangle;

namespace Map_Creator.MapInfo
{
    public class TileSet : TileSetStruct
    {
        public TileSet(Texture2D image,XnaPoint size, int index, Map map, string name, int ID = 0) : base(ID)
        {
            TilesImage = image;
            TilesSize = size;
            Index = index;
            AssociatedMap = map;
            Name = name;

            Tiles = new TileGrid(size.X,size.Y);
            for (var i = 0; i < size.X; i++)
            {
                for (var j = 0; j < size.Y; j++)
                {
                    Tiles[i, j] = new Tile {TileSetIndex = (short) index, Value = (short) (i + j*size.X)};
                }
            }

            DefinedAnimatedTiles = new AnimatedTileGrid(size.X,10);
            DefinedAutoTiles = new AutoTileGrid(size.X,10);
        }

        public Map AssociatedMap
        {
            get { return (Map)TileSetMap; }
            set { TileSetMap = value; }
        }

        public static event MapChangedDelegate PrimaryTileSetChanged;
        public static event MapChangedDelegate SelectedDataGridChanged;

        private void OnSelectedDataGridChanged()
        {
            var handler = SelectedDataGridChanged;
            if (handler != null) handler(AssociatedMap);
        }

        public static void OnPrimaryTileSetChanged(Map map)
        {
            var handler = PrimaryTileSetChanged;
            if (handler != null) handler(map);
        }

        private CustomDataGrid currentDataGrid;

        public CustomDataGrid CurrentDataGrid
        {
            get { return currentDataGrid; }
            set
            {
                currentDataGrid = value;
                OnSelectedDataGridChanged();
            }
        }

        public ExtendedTreeNode Node;

        public Selection Selection = new Selection(Map.SelectedMap.TileSize, new XnaPoint(1,1));
        public TileStructGrid SelectionSource;

        public float Zoom = 1f;

        public TileGrid Tiles;

        public AnimatedTileGrid DefinedAnimatedTiles;

        public AutoTileGrid DefinedAutoTiles;

        public XnaRectangle GetScreenSize(XnaRectangle tilesRectangle)
        {
            return new XnaRectangle(
                (int)(tilesRectangle.Location.X * TileSetMap.TileSize * Zoom),
                (int)(tilesRectangle.Location.Y * TileSetMap.TileSize * Zoom),
                (int)(tilesRectangle.Width * TileSetMap.TileSize * Zoom),
                (int)(tilesRectangle.Height * TileSetMap.TileSize * Zoom));
        }

        public void AddDataGrid(Type dataType, string name)
        {
            var dataGrid = new CustomDataGrid(dataType, TilesSize);

            dataGrid.Map = AssociatedMap;
            dataGrid.AssociatedTileSet = this;

            dataGrid.Name = name;

            DataGrids.Add(dataGrid);

            DataGridCount++;

            var dataGridNode = new ExtendedTreeNode(dataGrid.Name, NodeType.DataGrid,dataGrid);
            //dataGridNode.ContextMenuStrip = Main.Instance.LayerMenuStrip;

            dataGrid.Node = dataGridNode;
            if (!Node.Nodes.ContainsKey("Data Grids"))
                Node.Nodes.Add("Data Grids", "Data Grids");
            Node.Nodes["Data Grids"].Nodes.Add(dataGridNode);
        }

        public override void Delete()
        {
            if (AssociatedMap == null) return;

            var isUsed = AssociatedMap.IsTileSetUsed(this);
            if (isUsed)
                if (MessageBox.Show("The tile set is used\n" +
                                "do you really want to remove it?\n", "Tile Set Remove?", MessageBoxButtons.YesNo) == DialogResult.No)
                    return;

            // clear all usage of the tile set and readjust the index of other tiles
            for (int l = 0; l < AssociatedMap.Levels; l++)
            {
                var layer = AssociatedMap[l];
                for (int i = 0; i < AssociatedMap.GridSize.X; i++)
                {
                    for (int j = 0; j < AssociatedMap.GridSize.Y; j++)
                    {
                        var tileIndex = layer[i, j].TileSetIndex;
                        if (tileIndex == Index) layer[i, j] = null;
                        else if (tileIndex > Index && layer[i, j].Value != -1) layer[i, j].TileSetIndex -= 1;
                    }
                }
            }

            AssociatedMap.TileSets.Remove(this);

            foreach (var curTileSet in AssociatedMap.TileSets.Where(curTileSet => curTileSet.Index > Index))
            {
                curTileSet.Index--;
            }
            AssociatedMap.Sets--;

            if (AssociatedMap.CurrentTileSet == this)
            {
                if(AssociatedMap.Sets > 0)
                    AssociatedMap.CurrentTileSet = (TileSet)AssociatedMap.TileSets[Math.Min(Index, AssociatedMap.Sets - 1)];
                else AssociatedMap.CurrentTileSet = null;
            }

            TilesImage.Dispose();

            if (isUsed)
            {
                // Force Refresh
                var map = AssociatedMap;
                Map.SelectedMap = null;
                Map.SelectedMap = map;
            }

            var parent = Node.Parent;
            Node.Remove();
            if (parent.Nodes.Count == 0)
                parent.Remove();

            // set null associated map so remove wont ever happen twice :O
            AssociatedMap = null;

            base.Delete();
        }
    }
}
